package pl.jtb.ctl.tabory.ui.boe.ui.ce;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.log4j.Logger;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

import pl.jtb.ctl.tabory.dao.data.vo.CompositionVO;
import pl.jtb.ctl.tabory.dao.data.vo.VagonVO;
import pl.jtb.ctl.tabory.ui.boe.osgi.Activator;
import pl.jtb.ctl.tabory.ui.boe.selection.CompositionSelection;
import pl.jtb.ctl.tabory.ui.boe.selection.VagonSelection;
import pl.jtb.ctl.tabory.ui.boe.ui.ve.VagonMasterSectionPart;
import pl.jtb.ctl.tabory.ui.editors.AbstractDetailSectionPart;
import pl.jtb.ctl.tabory.ui.editors.EditorStateSL;
import pl.jtb.ctl.tabory.ui.osgi.UiBundleActivator;
import pl.jtb.ctl.tabory.ui.selection.ISelectionListener;

public class CompositionDetailSectionPart extends AbstractDetailSectionPart<CompositionSelection> {

    private final static Logger logger = Logger.getLogger(CompositionDetailSectionPart.class);
    private Composite client;
    private Text compositionName;
    private VagonMasterSectionPart allVagons;
    private VagonMasterSectionPart selectedVagons;
    private Button addVagonBtn;
    private Button removeVagonBtn;

    public CompositionDetailSectionPart(Composite parent, FormToolkit toolkit, int style, String sectionName) {
        super(parent, toolkit, style, sectionName);
    }

    @Override
    public CompositionSelection getSelection() {
        logger.debug("Getting selection");
        CompositionVO selectedComposition = selection.getSelectedComposition();
        if (selectedComposition == null) {
            selectedComposition = new CompositionVO();
        }
        selectedComposition.setInternalId(compositionName.getText());
        List<VagonVO> listCompositionVagons = selectedVagons.getSelection().getListVagons();
        Map<CompositionVO, List<VagonVO>> mapCompositionVagonRelation = selection.getMapCompositionVagonRelation();
        mapCompositionVagonRelation.put(selectedComposition, listCompositionVagons);
        selection.setMapCompositionVagonRelation(mapCompositionVagonRelation);
        selection.setSelectedComposition(selectedComposition);
        return selection;

    }

    @Override
    public void setSelection(CompositionSelection selection) {
        logger.debug("Setting selection: " + selection);
        this.selection = selection;
        logger.debug("Editor state: " + selection.getEditorState());
        switch (selection.getEditorState()) {
            case NEW:
                compositionName.setText("");
                fillDualTable(true);
                client.setVisible(true);
                setEnabled(true);
                compositionName.setFocus();
                break;
            case CLEAN:
                fillEditorValues();
                setEnabled(false);
                break;
            case EDITING:
                fillEditorValues();
                setEnabled(true);
                compositionName.setFocus();
                break;
        }
        allVagons.clearFilters();
        selectedVagons.clearFilters();
        allVagons.hideFilterComposite();
        selectedVagons.hideFilterComposite();
    }

    private void fillEditorValues() {
        CompositionVO selectedComposition = selection.getSelectedComposition();
        if (selectedComposition != null) {
            compositionName.setText(selectedComposition.getInternalId());
            fillDualTable(false);
            client.setVisible(true);
        } else {
            client.setVisible(false);
        }
    }

    private void fillDualTable(boolean isEnabled) {
        VagonSelection allVagonSelection = new VagonSelection();
        VagonSelection selectedVagonSelection = new VagonSelection();
        allVagonSelection.setEditorState(selection.getEditorState());
        selectedVagonSelection.setEditorState(selection.getEditorState());
        allVagonSelection.setMapCompositionVagons(selection.getMapCompositionVagonRelation());
        selectedVagonSelection.setMapCompositionVagons(selection.getMapCompositionVagonRelation());
        List<VagonVO> listAllVagons = selection.getListAllVagons();
        List<VagonVO> listCompositionVagons = selection.getMapCompositionVagonRelation().get(selection.getSelectedComposition());
        allVagonSelection.setListVagons(listAllVagons);
        selectedVagonSelection.setListVagons(listCompositionVagons);
        allVagons.setSelection(allVagonSelection);
        selectedVagons.setSelection(selectedVagonSelection);
        if (selection.getEditorState().equals(EditorStateSL.CLEAN)) {
            allVagons.setEnabled(false);
            selectedVagons.setEnabled(false);
        } else {
            allVagons.setEnabled(true);
            selectedVagons.setEnabled(true);
        }
    }

    @Override
    public void addSelectionListener(ISelectionListener<CompositionSelection> listner) {
    }

    @Override
    public void removeSelectionListener(ISelectionListener<CompositionSelection> listner) {
    }

    @Override
    protected void initGui(Section parentSection, FormToolkit toolkit) {
        logger.debug("Initializing GUI.");

        GridLayoutFactory.fillDefaults().numColumns(1).applyTo(parentSection);
        client = toolkit.createComposite(parentSection);
        GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(client);
        parentSection.setClient(client);

        Label labelUserName = toolkit.createLabel(client, Activator.getMessage("compositions.master.label.name"));
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(false, false).applyTo(labelUserName);
        compositionName = toolkit.createText(client, null);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(false, false).hint(120, SWT.DEFAULT).applyTo(compositionName);

        Composite dualTableComposite = toolkit.createComposite(client);
        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(4).applyTo(dualTableComposite);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).span(2, 1).applyTo(dualTableComposite);

        Set<VagonMasterSectionPart.AvailableColumnsSL> setAllColumns = new HashSet<VagonMasterSectionPart.AvailableColumnsSL>();
        setAllColumns.add(VagonMasterSectionPart.AvailableColumnsSL.COLUMN_COMPOSITION_NAME);
        setAllColumns.add(VagonMasterSectionPart.AvailableColumnsSL.COLUMN_VAGON_NAME);
        allVagons = new VagonMasterSectionPart(dualTableComposite, toolkit, Section.TITLE_BAR, Activator.getMessage("compositions.master.label.dualtable.allvagons"), false, true, setAllColumns);
        GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.FILL).grab(false, true).applyTo(allVagons.getSection());

        Composite buttonComposite = toolkit.createComposite(dualTableComposite);
        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(1).applyTo(buttonComposite);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(false, true).applyTo(buttonComposite);

        addVagonBtn = toolkit.createButton(buttonComposite, "", SWT.FLAT);
        addVagonBtn.setImage(UiBundleActivator.getImage("icons\\Arrow-Left.png"));
        addVagonBtn.setToolTipText(Activator.getMessage("compositions.master.label.dualtable.addvagon"));
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(false, false).applyTo(addVagonBtn);
        removeVagonBtn = toolkit.createButton(buttonComposite, "", SWT.FLAT);
        removeVagonBtn.setImage(UiBundleActivator.getImage("icons\\Arrow-Right.png"));
        removeVagonBtn.setToolTipText(Activator.getMessage("compositions.master.label.dualtable.removevagon"));
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(false, false).applyTo(removeVagonBtn);

        Set<VagonMasterSectionPart.AvailableColumnsSL> setSelectedColumns = new HashSet<VagonMasterSectionPart.AvailableColumnsSL>();
        setSelectedColumns.add(VagonMasterSectionPart.AvailableColumnsSL.COLUMN_VAGON_NAME);
        selectedVagons = new VagonMasterSectionPart(dualTableComposite, toolkit, Section.TITLE_BAR, Activator.getMessage("compositions.master.label.dualtable.selectedvagons"), false, true, setSelectedColumns);
        GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.FILL).grab(false, true).applyTo(selectedVagons.getSection());

        Label spacer = toolkit.createLabel(dualTableComposite, "");
        GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.FILL).grab(false, true).applyTo(spacer);

        toolkit.adapt(client);
        toolkit.paintBordersFor(client);
        client.setVisible(false);

    }

    @Override
    protected void postInitGui(Section parentSection, FormToolkit toolkit) {
        selectedVagons.getTable().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseDoubleClick(MouseEvent e) {
                performRemoveVagon();
            }
        });
        allVagons.getTable().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseDoubleClick(MouseEvent e) {
                performAddVagon();
            }
        });
    }

    @Override
    protected void initActions() {
        selectedVagons.addSelectionListener(new ISelectionListener<VagonSelection>() {

            @Override
            public void selectionChanged(VagonSelection selection) {
                logger.debug("Selection changed");
            }
        });
        allVagons.addSelectionListener(new ISelectionListener<VagonSelection>() {

            @Override
            public void selectionChanged(VagonSelection selection) {
                logger.debug("Selection changed");

            }
        });
        addVagonBtn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                performAddVagon();
            }
        });
        removeVagonBtn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                performRemoveVagon();
            }
        });

    }

    private void performRemoveVagon() {
        VagonSelection selection = selectedVagons.getSelection();
        VagonVO selectedVagon = selection.getSelectedVagon();
        selection.getListVagons().remove(selectedVagon);
        selectedVagons.setSelection(selection);
        selectedVagons.setEnabled(true);
        allVagons.setEnabled(true);
    }

    private void performAddVagon() {
        VagonSelection selectedVagonsSelection = selectedVagons.getSelection();
        VagonVO selectedVagon = allVagons.getSelection().getSelectedVagon();
        if (selectedVagon == null) {
            return;
        }
        allVagons.getSelection().getListVagons().remove(selectedVagon);
        List<VagonVO> listSelectedVagons = selectedVagonsSelection.getListVagons();
        if (listSelectedVagons == null) {
            listSelectedVagons = new ArrayList<VagonVO>();
            selectedVagonsSelection.setListVagons(listSelectedVagons);
        }
        for (VagonVO vagonVO : listSelectedVagons) {
            if (vagonVO.getId().equals(selectedVagon.getId())) {
                return;
            }
        }
        Map<CompositionVO, List<VagonVO>> mapCompositionVagonRelation = selection.getMapCompositionVagonRelation();
        for (Entry<CompositionVO, List<VagonVO>> entry : mapCompositionVagonRelation.entrySet()) {
            List<VagonVO> listVagons = entry.getValue();
            for (Iterator<VagonVO> iterator = listVagons.iterator(); iterator.hasNext();) {
                VagonVO vagonVO = iterator.next();
                if (vagonVO.equals(selectedVagon)) {
                    iterator.remove();
                    break;
                }
            }
        }
        selection.setMapCompositionVagonRelation(mapCompositionVagonRelation);
        selectedVagonsSelection.getListVagons().add(selectedVagon);
        selectedVagons.setSelection(selectedVagonsSelection);
        allVagons.getSelection().getListVagons().add(selectedVagon);
        allVagons.setSelection(allVagons.getSelection());
        allVagons.setEnabled(true);
        selectedVagons.setEnabled(true);
    }

    @Override
    public void setEnabled(boolean isEnabled) {
        compositionName.setEnabled(isEnabled);
        addVagonBtn.setEnabled(isEnabled);
        removeVagonBtn.setEnabled(isEnabled);

    }

}
